<template>
	<div class="calender-container">
		<div class="calender-content" :style="{ minHeight: isWeek ? '200rpx' : '400px' }">
			<!-- 头部 -->
			<div class="calender-title">
				<uni-collapse accordion @change="handleChangeCalender">
					<uni-collapse-item :open="openCalender" :show-arrow="false" title-border="none" :border="false">
						<template v-slot:title>
							<div class="calender-title-left">
								{{ checkedDay }}
							</div>
						</template>
						<view style="height: 55vh; background: #fff">
							<zengCalenVue :chooseDay="chooseDays" @onDayClick="onDayClick" style="margin-top: 33rpx"></zengCalenVue>
						</view>
					</uni-collapse-item>
				</uni-collapse>
			</div>
			<!-- 周历 -->
			<transition name="fade" v-if="!openCalender">
				<div class="month-container" @touchstart="handleMoveStart" @touchend="handleMoveEnd" @touchmove="handleMove" :class="{ transition: transition }" :style="{
            transform:
              'translate3d(' +
              calenderMove.x +
              'px,' +
              calenderMove.y +
              'px,0px)',
            height: isWeek ? '70px' : '300px',
          }">
					<div v-for="(month, index) in monthList" :key="index" class="month-item">
						<div v-for="(week, weekindex) in month" :key="weekindex" class="month-week">
							<div v-for="(day, dayindex) in week" :class="{
                  ischecked: checkedDay == day.date,
                  istoday: day.istoday,
                }" @click.stop="chooseDay(day)" :key="dayindex" class="month-week-item">
								<div class="week-day" :class="{
                    ischecked: checkedDay == day.date,
                    othermonth: day.othermonth,
                    istoday: day.istoday,
                  }">
									<span class="one-day">
                    <i class="day" :class="day.istoday ? 'today' : ''">{{
                      WEEK_LIST[day.w]["text"]
                    }}</i>
                  </span>
									<!-- <span class="one-day">
                    <i class="day" :class="day.istoday ? 'today' : ''">{{ day.day }}</i>
                  </span> -->
								</div>
							</div>
						</div>
					</div>
				</div>
			</transition>
		</div>
	</div>
</template>

<script setup lang="ts">
	import { ref, onMounted } from "vue";
	import zengCalenVue from "../zeng-calen/components/zeng-calen/zeng-calen.vue";
	const popup = ref(null); // uni_popup 弹框实例
	const openCalender = ref(false); // 是否打开日历
	// 头部星期列表
	const WEEK_LIST = [{
			text: "日",
		},
		{
			text: "一",
		},
		{
			text: "二",
		},
		{
			text: "三",
		},
		{
			text: "四",
		},
		{
			text: "五",
		},
		{
			text: "六",
		},
	];
	const dispDate = ref < Date > (new Date()); //当前时间
	type DayType = {
		date ? : string | number;
		istoday ? : boolean;
		othermonth ? : boolean;
	};
	type MonthList = DayType[];
	const monthList = ref < MonthList > ([]);
	const today = ref < Date > (new Date()); //当前时间
	const checkedDay = ref(""); //选中时间
	const currentDay = ref < Date > (new Date()); //当前时间
	const transition = ref < boolean > (true); //是否显示动画
	const calenderHeight = ref < number > (-100); //日历的高度
	const calenderMove = ref({
		x: 0,
		y: 0
	});
	const moveStartX = ref < number > (0); //开始移动的位置x轴
	const moveStartY = ref < number > (0); //开始移动的位置y轴
	const moveStartCalenderHeight = ref < number > (0); //开始移动的高度初始值
	const itemWidth = ref < number > (0); //窗口的宽度
	const moveIndex = ref < number > (0); // 左右移动 1 向右移动,-1向左移动,点击天0
	const isWeek = ref < boolean > (true); //是否是周历模式
	onMounted(() => {
		todayDate();
		get3week();
	});
	uni.$on("chooseDay", () => {
		checkedDay.value = formatDateTime(today.value);
	});
	const handleOpenPopup = () => {
		popup.value.open();
	};
	const handleChangeCalender = (e) => {
		openCalender.value = !openCalender.value;
	};
	//用户选择的日期
	const chooseDays = ref([{
			data: "2024-05-07",
			sleep: 1,
			qi: 1
		},
		{
			data: "2024-05-08",
			sleep: 0,
			qi: 0
		},
		{
			data: "2024-05-09",
			sleep: 0,
			qi: 0
		},
		{
			data: "2024-05-10",
			sleep: 0,
			qi: 0
		},
		{
			data: "2024-05-11",
			sleep: 0,
			qi: 0
		},
		{
			data: "2024-05-12",
			sleep: 0,
			qi: 0
		},
		{
			data: "2024-05-13",
			sleep: 0,
			qi: 0
		},
		{
			data: "2024-05-14",
			sleep: 0,
			qi: 0
		},
		{
			data: "2024-05-15",
			sleep: 0,
			qi: 0
		},
		{
			data: "2024-05-16",
			sleep: 0,
			qi: 0
		},
	]);

	const onDayClick = (e) => {
		checkedDay.value = e.date;
		openCalender.value = !openCalender.value;
	};
	const onMonthChange = () => {};
	const close = () => {};
	const selectDay = ref < Date > (new Date());
	/**
	 * 获取今天日期
	 */
	const todayDate = () => {
		checkedDay.value = formatDateTime(today.value);
		selectDay.value = new Date(checkedDay.value);
	};
	/**
	 * 转换时间格式
	 * @param date 标准时间
	 */
	const formatDateTime = (date: Date): string => {
		let y = date.getFullYear();
		let m: string = date.getMonth() + 1 + "";
		m = Number(m) < 10 ? "0" + m : m;
		let d = date.getDate() + "";
		d = Number(d) < 10 ? "0" + d : d;
		return y + "-" + m + "-" + d;
	};

	interface weekParams {
		mode: string;
		day: number;
		year: number;
		month: number;
		date: string;
		w: string;
		//日历要显示的其他内容
		istoday: boolean;
		ischecked: boolean;
		othermonth ? : number | boolean;
	}
	/**
	 * 创建单月历
	 * @param year 年
	 * @param month 月
	 */
	const getMonth = (year: number, month: number): DayType => {
		let monthArr = [];
		let dtFirst = new Date(year, month, 1); //每个月第一天
		let dtLast = new Date(year, month + 1, 0); //每个月最后一天
		let monthLength = dtLast.getDate() - dtFirst.getDate() + 1;
		let space = (dtFirst.getDay() - 1 + 7) % 7; //月历前面空格

		for(let i = -space; i < 36; i += 7) {
			let week = [];
			for(let j = 0; j < 7; j++) {
				let day = i + j + 1;
				if(day > 0 && day <= monthLength) {
					let weekItem: weekParams = {
						mode: "month",
						day: day,
						year: year,
						month: month,
						date: format(year, month, day),

						istoday: today.value.getFullYear() === year &&
							today.value.getMonth() === month &&
							today.value.getDate() === day ?
							true :
							false,
						ischecked: false,
					};
					week.push(weekItem);
				} else {
					//其它月份
					let newdt = new Date(year, month, day);
					let years = newdt.getFullYear();
					let months = newdt.getMonth();
					let days = newdt.getDate();
					let weeksItem: weekParams = {
						mode: "month",
						day: days,
						year: years,
						month: months,
						date: format(year, month, day),

						istoday: today.value.getFullYear() === years &&
							today.value.getMonth() === months &&
							today.value.getDate() === days ?
							true :
							false,
						ischecked: false,
						othermonth: day <= 0 ? -1 : 1,
					};
					week.push(weeksItem);
				}
			}
			monthArr.push(week);
		}
		return monthArr;
	};

	/**
	 * 转换时间
	 * @param year 年
	 * @param month 月
	 * @param day 日
	 */
	const format = (year: number, month: number, day: number | string) => {
		month++;
		let m = month < 10 ? "0" + month : month;
		day < 10 && (day = "0" + day);
		return year + "-" + m + "-" + day;
	};
	/**
	 * 选中某一天
	 * @param year 年
	 * @param month 月
	 * @param day 日
	 * @param othermonth 其他月份，当前月前面空值
	 * @param mode 类型，'month','week'
	 */
	interface chooseDayParams {
		year: number;
		month: number;
		day: number;
		othermonth: number;
		mode: string;
	}

	interface Thing {
		date: string;
		infos ? : ThingInfo[];
	}

	interface ThingInfo {
		title: string;
		address: string;
		dates: string;
	}
	const chooseDay = ({
		year,
		month,
		day,
		othermonth,
		mode,
	}: chooseDayParams): void => {
		currentDay.value = new Date(year, month, day); //标准时间
		checkedDay.value = format(year, month, day); //"2020-11-11"
		if(othermonth && mode === "month") {
			let tmpDt = new Date(
				dispDate.value.getFullYear(),
				dispDate.value.getMonth() - othermonth,
				0
			);
			let maxday = tmpDt.getDate();
			let days = maxday < day ? maxday : day;
			dispDate.value = new Date(year, month - othermonth, days);
			changeIndex(othermonth || 0, true);
		} else {
			dispDate.value = currentDay.value;
		}
	};
	/**
	 * 获取三周
	 */
	const get3week = () => {
		let year = dispDate.value.getFullYear();
		let month = dispDate.value.getMonth();
		let day = dispDate.value.getDate();
		monthList.value = [];
		monthList.value.push(getWeek(year, month, day - 7));
		monthList.value.push(getWeek(year, month, day));
		monthList.value.push(getWeek(year, month, day + 7));
		console.log("monthList", monthList.value);
	};
	/**
	 * 获取星期
	 * @param year 为选中当天的年
	 * @param month 为选中当天的月
	 * @param day 为选中当天的日
	 */
	const getWeek = (year: number, month: number, day: number) => {
		let dt = new Date(year, month, day);
		let weekArr = [];
		let dtFirst = new Date(year, month, day - ((dt.getDay() + 6) % 7));
		let week = [];
		//循环选中当天所在那一周的每一天
		for(let j = 0; j < 7; j++) {
			let newdt = new Date(
				dtFirst.getFullYear(),
				dtFirst.getMonth(),
				dtFirst.getDate() + j
			);
			let years = newdt.getFullYear();
			let months = newdt.getMonth();
			let days = newdt.getDate();
			let w = newdt.getDay();
			let weekItem: weekParams = {
				mode: "week",
				day: days,
				year: years,
				month: months,
				w: w,
				date: format(years, months, days),

				istoday: today.value.getFullYear() === years &&
					today.value.getMonth() === months &&
					today.value.getDate() === days ?
					true :
					false,
				ischecked: false,
				othermonth: months !== month,
			};
			week.push(weekItem);
		}
		weekArr.push(week);
		return weekArr;
	};
	/**
	 * 左右移动
	 * @param index 月的index
	 * @param isWeek 是否显示周
	 * @param isClick 移动不可点击
	 */
	const changeIndex = (index: number, isClick = false) => {
		if(isWeek.value) {
			dispDate.value = new Date(
				dispDate.value.getFullYear(),
				dispDate.value.getMonth(),
				dispDate.value.getDate() + 7 * index
			);
			currentDay.value = dispDate.value;
			get3week();
		} else {
			let tmpDt = new Date(
				dispDate.value.getFullYear(),
				dispDate.value.getMonth() + index,
				0
			);
			let maxday = tmpDt.getDate();
			let days =
				maxday < dispDate.value.getDate() ? maxday : dispDate.value.getDate();
			dispDate.value = new Date(
				dispDate.value.getFullYear(),
				dispDate.value.getMonth() + index,
				days
			);
			if(!isClick) {
				checkedDay.value = format(
					dispDate.value.getFullYear(),
					dispDate.value.getMonth(),
					dispDate.value.getDate()
				);
			}
		}
	};
	/**
	 * 手机端端开始移动
	 * @param e event
	 */
	const handleMoveStart = (e: any) => {
		let touch = e ? .changedTouches[0] || e;
		moveStartX.value = touch.clientX;
		moveStartY.value = touch.clientY;
		moveStartCalenderHeight.value = calenderHeight.value;
		moveIndex.value = 0;
	};

	/**
	 * 手机端端移动
	 * @param e event
	 */
	const handleMove = (e: any) => {
		let touch = e ? .changedTouches[0] || e;
		calenderMove.value.x = touch.clientX - moveStartX.value;
	};
	/**
	 * 手机端端结束移动
	 * @param e event
	 */
	const handleMoveEnd = (e: any) => {
		let touch = e ? .changedTouches[0] || e;
		if(moveStartX.value < touch.clientX) {
			if(moveStartX.value - touch.clientX < -150) {
				calenderMove.value.x = itemWidth.value;
				moveIndex.value = -1;
			} else {
				calenderMove.value.x = 0;
			}
		} else {
			if(moveStartX.value - touch.clientX > 150) {
				calenderMove.value.x = -itemWidth.value;
				moveIndex.value = 1;
			} else {
				calenderMove.value.x = 0;
			}
		}

		changeIndex(moveIndex.value, false);
	};

	/**
	 * 切换月或周
	 * @param e event
	 */
	const toggleMove = () => {
		isWeek.value = !isWeek.value;
		if(isWeek.value) {
			get3week();
		}
	};
</script>
<style scoped lang="scss">
	.calender-container {
		margin: 16px;
		color: #232323;
		.calender-content,
		.things-content {
			box-shadow: -2px -2px 16px #d9dee7, 2px 2px 16px #d9dee7;
			padding: 14px;
			min-width: 320px;
			min-height: 400px;
			overflow: hidden;
			border-radius: 7px;
			.calender-title {
				display: flex;
				align-items: center;
				justify-content: center;
				&-left {
					display: flex;
					align-items: center;
					justify-content: center;
					font-weight: 600;
					font-size: 36rpx;
					color: #ffffff;
					width: 287rpx;
					height: 56rpx;
					background: linear-gradient(90deg, #cb9fff 0%, #a28aff 100%) !important;
					border-radius: 91rpx 91rpx 91rpx 91rpx;
				}
			}
			.week-head-con {
				display: flex;
				align-items: center;
				padding-top: 20px;
				.week-head-item {
					width: 14.2%;
					text-align: center;
				}
			}
			.month-container {
				display: flex;
				position: relative;
				height: 300px;
				.month-item {
					position: absolute;
					width: 100%;
					min-height: 64px;
					// border-right: 1px solid #eee;
					padding-top: 20px;
					.month-week {
						display: flex;
						align-items: center;
						.month-week-item {
							width: 14.2%;
							text-align: center;
							position: relative;
						}
					}
				}
				.month-item:nth-child(1) {
					left: -100%;
				}
				.month-item:nth-child(2) {
					left: 0;
				}
				.month-item:nth-child(3) {
					left: 105%;
				}
				.week-day i {
					display: block;
					text-align: center;
					font-style: normal;
					padding: 1px;
					line-height: 58rpx;
					height: 58rpx;
					width: 58rpx;
				}
				.week-day.ischecked i {
					border-radius: 16rpx;
					color: #fff !important;
					background: #8e70ff;
				}
				.thing a {
					color: #fff;
					background: #fff;
				}
				.thing {
					position: absolute;
					left: 50%;
					bottom: 2px;
					transform: translateX(-50%);
					color: #f5a623;
				}
				.thing a {
					cursor: pointer;
					display: block;
					width: 8px;
					height: 8px;
					word-break: break-all;
					line-height: 8px;
					color: #f5a623;
					background: #f5a623;
					border-radius: 50%;
				}
				.othermonth {
					color: #333333;
				}
				.istoday .today {
					color: #fff;
					background: #8e70ff;
					border-radius: 16rpx;
				}
			}
		}
		.things-content {
			margin-top: 20px;
			min-height: 180px;
			font-size: 14px;
			color: #666666;
			.van-swipe {
				min-height: 180px;
			}
			p {
				display: flex;
				align-items: center;
			}
			.title.thing-title::before {
				content: "";
				display: inline-block;
				width: 4px;
				height: 18px;
				background: #8e70ff;
				margin-right: 6px;
				position: relative;
				bottom: -2px;
			}
			.title {
				color: #999999;
			}
		}
	}
	
	::v-deep .uni-collapse-item__title-box {
		color: #fff;
		background: linear-gradient(90deg, #cb9fff 0%, #a28aff 100%);
		justify-content: center;
		border-radius: 91rpx 91rpx 91rpx 91rpx;
		width: 287rpx;
		height: 56rpx;
		font-weight: 600;
		font-size: 36rpx;
	}
	
	::v-deep .uni-collapse-item__title.uni-collapse-item-border {
		border-bottom: none !important;
	}
	
	::v-deep .uni-collapse-item__title-wrap {
		display: flex;
		justify-content: center;
	}
</style>